package tech.xs.workflow.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.xs.common.framework.service.CrudServiceImpl;
import tech.xs.workflow.bpmn.element.ProcessElement;
import tech.xs.workflow.bpmn.element.event.BaseEventElement;
import tech.xs.workflow.bpmn.element.event.EndEventElement;
import tech.xs.workflow.bpmn.element.event.StartEventElement;
import tech.xs.workflow.dao.BpmnEventDao;
import tech.xs.workflow.dao.WorkflowTaskDao;
import tech.xs.workflow.domain.entity.BpmnEvent;
import tech.xs.workflow.domain.entity.BpmnProcess;
import tech.xs.workflow.domain.entity.WorkflowTask;
import tech.xs.workflow.domain.entity.WorkflowWork;
import tech.xs.workflow.domain.enums.BpmnEventTypeEnum;
import tech.xs.workflow.domain.enums.BpmnNodeTypeEnum;
import tech.xs.workflow.domain.enums.WorkFlowTaskStatusEnum;
import tech.xs.workflow.domain.exception.BpmnException;
import tech.xs.workflow.service.BpmnEventService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class BpmnEventServiceImpl extends CrudServiceImpl<BpmnEventDao, BpmnEvent> implements BpmnEventService {

    @Resource
    private WorkflowTaskDao workflowTaskDao;

    @Override
    public void importEvent(BpmnProcess process, ProcessElement processElement) {
        List<BaseEventElement> events = processElement.getEvents();
        if (events == null) {
            return;
        }
        List<BpmnEvent> eventList = new ArrayList<>();
        for (BaseEventElement item : events) {
            if (item == null) {
                throw new BpmnException("事件不能为空");
            }
            BpmnEvent bpmnEvent = new BpmnEvent();
            bpmnEvent.setProcessId(process.getId());
            bpmnEvent.setNodeId(item.getId());
            bpmnEvent.setName(item.getName());
            if (item instanceof StartEventElement) {
                bpmnEvent.setEventType(BpmnEventTypeEnum.START_EVENT);
            } else if (item instanceof EndEventElement) {
                bpmnEvent.setEventType(BpmnEventTypeEnum.END_EVENT);
            } else {
                throw new BpmnException("不支持的节点事件类型:" + item.getClass().getName() + " " + item);
            }
            eventList.add(bpmnEvent);
        }
        if (!eventList.isEmpty()) {
            saveBatch(eventList);
        }
    }

    @Override
    public boolean execute(WorkflowWork work, BpmnEvent node) {
        log.info("执行流程事件-开始 work:" + work + " node:" + node);
        switch (node.getEventType()) {
            case START_EVENT: {
                return executeStartEvent(work, node);
            }
            case END_EVENT: {
                return executeEndEvent(work, node);
            }
            default: {
                throw new BpmnException("未知的事件类型:" + node);
            }
        }
    }

    private boolean executeStartEvent(WorkflowWork work, BpmnEvent node) {
        WorkflowTask workflowTask = getWorkflowTask(work, node);
        workflowTaskDao.insert(workflowTask);
        return true;
    }

    private boolean executeEndEvent(WorkflowWork work, BpmnEvent node) {
        WorkflowTask workflowTask = getWorkflowTask(work, node);
        workflowTaskDao.insert(workflowTask);
        return false;
    }

    private WorkflowTask getWorkflowTask(WorkflowWork work, BpmnEvent node) {
        WorkflowTask workflowTask = new WorkflowTask();
        workflowTask.setDefineId(work.getDefineId());
        workflowTask.setWorkId(work.getId());
        workflowTask.setBpmnId(work.getBpmnId());
        workflowTask.setBpmnNodeId(node.getId());
        workflowTask.setBpmnNodeType(BpmnNodeTypeEnum.EVENT);
        workflowTask.setBpmnNodeName(node.getName());
        workflowTask.setTaskStatus(WorkFlowTaskStatusEnum.COMPLETE);
        workflowTask.setTaskStartDate(new Date());
        workflowTask.setTaskEndDate(new Date());
        return workflowTask;
    }

}
